<?php
/**
 * GeryEngine
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this release in the file LICENSE
 *
 * @copyright  Copyright (c) 2007 Arjen Brouwer
 * @license    New BSD License
 * @author     Arjen Brouwer
 */

class RuntimeServices {
	
	private $macros;
	private $engine;
	
	private $templateStack;
	
	public function __construct(GeryEngine $engine) {
		$this->engine = $engine;
		$this->macros = new HashMap();
		$this->templateStack = array();
	}
	
	public function getTemplate($resourceName) {
		return $this->engine->getTemplate($resourceName);
	}
	
	public function getResource($resourceName) {
		return $this->engine->getResource($resourceName);
	}
	
	public function getLogger() {
		return $this->engine->getLogger();
	}
	
	public function getEngine() {
		return $this->engine;
	}
	
	/** Template location **/
	public function pushTemplateName($templateName, $macroName = null) {
		$this->templateStack[] = array($templateName, $macroName);
	}
	
	public function popTemplateName() {
		array_pop($this->templateStack);	
	}
	
	public function getTemplateName() {
		return $this->templateStack[count($this->templateStack) - 1][0];
		
	}

	public function getMacroName() {
		return $this->templateStack[count($this->templateStack) - 1][1];
	}
	
	public function getLocation($lineNumber) {
		return new TemplateLocation($lineNumber, $this->getTemplateName(), $this->getMacroName());
	}
	
	
	/** Macro methods **/
	public function registerMacro($templateClass, $macroName) {
		$methodName = GeryMacroNamer::getMethodName($macroName);
		
		$this->macros->put($macroName,
			new MethodProxy($templateClass, $methodName));
	}
	
	public function isMacroRegistered($macroName) {
		return $this->macros->containsKey($macroName);
	}
	
	public function callMacro($macroName, $context, $parameters) {
		$macro = $this->macros->get($macroName);
		
		if ($macro == null)
			return false;
		
		return $macro->call(array($this, $context, $parameters));
	}
	
	public function getClassNameForMacro($macroName) {
		$macro = $this->macros->get($macroName);
		
		return $macro->getClassName();
	}
	
	/** Logging **/
	public function log($message, $lineNumber, $level = LOG_LEVEL_INFO) {
		
		$location = $this->getLocation($lineNumber);
		
		$this->getLogger()->log($message . ' in ' . $location->__toString(), $level);	

		if ($level == LOG_LEVEL_FATAL) {
			throw new GeryRuntimeException($message, $location);
		}
	}
	
	public function error($message, $lineNumber) {
		$this->log($message, $lineNumber, LOG_LEVEL_ERROR);
	}
}
?>